package com.yint.tree;

import java.util.HashMap;
import java.util.Map;

/**
 * 树接口节点
 * <p>
 * Created by 殷田 on 2018/5/3.
 */
public class Tree {
    private Leaf head;
    private Leaf currentLeft;
    private STATUS state = STATUS.UNINIT;

    public Tree() {
    }

    public Tree(Leaf head) {
        setHead(head);
    }

    public final void setHead(Leaf head) {
        this.head = head;
        if (currentLeft == null) {
            currentLeft = head;
        }
    }

    public final boolean entry() {
        if (getHead() == null) {
            return false;
        }
        if (!onEntry()) {
            return false;
        }
        return true;
    }

    public final STATUS tick() {
        state = onTick(currentLeft);
        if (state == STATUS.FAILED && head != currentLeft) {
            state = onTick(head);
        }
        return state;
    }

    public final void leave() {
        onLeave();
        head.leave(this);
        currentLeft = null;
        state = STATUS.SUCCEED;
    }

    protected boolean onEntry() {
        return getState() != STATUS.FAILED;
    }

    protected STATUS onTick(Leaf leaf) {
        STATUS state = STATUS.FAILED;
        if (leaf != null) {
            if (leaf.entry(this)) {
                return leaf.tick(this);
            } else {
                leaf.leave(this);
            }
        }
        return state;
    }

    protected STATUS getState() {
        return state;
    }

    protected void onLeave()
    {
    	
    }

    protected Leaf getCurrentLeaf() {
        return currentLeft;
    }

    protected void setCurrentLeaf(Leaf leaf) {
        this.currentLeft = leaf;
    }

    protected Leaf getHead() {
        return head;
    }

    private Map< String, Object > params = new HashMap< String, Object >();

	public boolean isExist( String key )
	{
		return params.containsKey( key );
	}

	public void addParam( String key, Object data )
	{
		if ( params.containsKey( key ) )
		{
			removeParam( key );
		}
		params.put( key, data );
	}

	public Object getParam( String key )
	{
		if ( params.containsKey( key ) )
		{
			return params.get( key );
		}
		return null;
	}

	public void removeParam( String key )
	{
		params.remove( key );
	}

	public void clearParam()
	{
		params.clear();
	}

    public final void addString(String key, String data) {
        addParam(key, data);
    }

    public final void addInt(String key, int data) {
        addParam(key, data);
    }

    public final void addFloat(String key, float data) {
        addParam(key, data);
    }

    public final void addLong(String key, long data) {
        addParam(key, data);
    }

    public final void addBoolean(String key, boolean data) {
        addParam(key, data);
    }

    public final void addByte(String key, byte data) {
        addParam(key, data);
    }

    public final String getString(String key) {
        return (String) getParam(key);
    }

    public final boolean getBoolean(String key) {
        return (boolean) getParam(key);
    }

    public final int getInt(String key) {
        return (int) getParam(key);
    }

    public final long getLong(String key) {
        return (long) getParam(key);
    }

    public final float getFloat(String key) {
        return (float) getParam(key);
    }

    public final double getDouble(String key) {
        return (double) getParam(key);
    }

    public final byte getByte(String key) {
        return (byte) getParam(key);
    }
}
